package com.yckj.activechicken.business.common.service.impl;

import com.yckj.activechicken.business.common.mapper.ApproverInfoMapper;
import com.yckj.activechicken.business.common.model.ApproverInfo;
import com.yckj.activechicken.business.common.model.ApproverInfoExample;
import com.yckj.activechicken.business.common.model.vo.HistoricActivity;
import com.yckj.activechicken.business.common.service.IProcessService;
import com.yckj.activechicken.business.hr.mapper.HrEmployeeMapper;
import com.yckj.activechicken.business.hr.model.HrEmployee;
import com.yckj.activechicken.business.hr.model.HrEmployeeExample;
import com.yckj.activechicken.business.system.mapper.SysUserMapper;
import com.yckj.activechicken.business.system.model.SysUser;
import com.yckj.activechicken.business.system.model.SysUserExample;
import com.yckj.activechicken.common.constant.ProcessContants;
import com.yckj.activechicken.common.utils.StringUtils;
import com.yckj.activechicken.common.utils.security.SecurityUtils;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * <p>
 * Title:com.yckj.activechicken.business.common.service.impl
 * </p>
 * <p/>
 * <p>
 * Description: 描述【流程管理通用业务处理实体】
 * </p>
 * <p/>
 * <p>
 * Copyright: Copyright (c) 2019
 * </p>
 * <p/>
 * <p>
 * Company: 英才汇硕信息技术有限公司
 * </p>
 *
 * @author zhoujy
 * @version 1.0
 * @created 2020/5/27 9:03
 */
@Service
public class ProcessServiceImpl implements IProcessService {

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private HrEmployeeMapper hrEmployeeMapper;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ApproverInfoMapper approverInfoMapper;

    @Autowired
    private RuntimeService runtimeService;



    /**
     * 查询审批历史列表
     * @param processInstanceId
     * @return
     */
    @Override
    public List<HistoricActivity> selectHistoryList(String processInstanceId) {
        List<HistoricActivity> activityList = new ArrayList<>();
        HistoricActivityInstanceQuery query = historyService.createHistoricActivityInstanceQuery();
        List<HistoricActivityInstance> list = query.processInstanceId(processInstanceId)
                .activityType("userTask")
                .finished()
                .orderByHistoricActivityInstanceStartTime()
                .desc()
                .list();
        list.forEach(instance -> {
            HistoricActivity activity = new HistoricActivity();
            BeanUtils.copyProperties(instance, activity);
            String taskId = instance.getTaskId();
            List<Comment> comment = taskService.getTaskComments(taskId, "comment");
            if (!CollectionUtils.isEmpty(comment)) {
                activity.setComment(comment.get(0).getFullMessage());
            }

            SysUserExample sysUserExample = new SysUserExample();
            sysUserExample.createCriteria().andUserNameEqualTo(instance.getAssignee());
            List<SysUser> sysUserList = sysUserMapper.selectByExample(sysUserExample);
            if (StringUtils.isNotEmpty(sysUserList)) {
                HrEmployeeExample hrEmployeeExample = new HrEmployeeExample();
                hrEmployeeExample.createCriteria().andEmpIdEqualTo(sysUserList.get(0).getEmpId());
                List<HrEmployee> hrEmployeeList = hrEmployeeMapper.selectByExample(hrEmployeeExample);
                if(StringUtils.isNotEmpty(hrEmployeeList)){
                    activity.setAssigneeName(hrEmployeeList.get(0).getName());
                }

            }
            activityList.add(activity);
        });
        return activityList;
    }

    /**
     * 获取当前审批节点的审批选择类型，获取活动节点的连线信息
     * @param taskId
     * @return
     */
    @Override
    public List<String> queryApprovalType(String taskId) {
        List<String> outList = new ArrayList<>();

        //获取节点任务
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        //获取流程定义模型
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());

        //获取当前节点的定义模型
        FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());

        //转换为用户任务
        UserTask userTask = (UserTask)flowElement;

        //获取该节点出口连线
        List<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
        if(StringUtils.isNotEmpty(outgoingFlows)){
            for(SequenceFlow sequenceFlow : outgoingFlows){
                outList.add(sequenceFlow.getName());
            }
        }
        return outList;
    }


    /**
     * 办理当前任务，并设置下一环节办理人，公共组件方法
     * @param queryMap
     * @return
     */
    @Override
    public Map<String,String> doTaskAndStartNextTask(Map<String,String> queryMap){
        Map<String,String> outMap = new HashMap<>(2);
        String username = SecurityUtils.getUsername();

        String applyUser = queryMap.get("applyUser");
        String taskId = queryMap.get("taskId");
        String processInstanceId = queryMap.get("processInstanceId");
        String approval = queryMap.get("approval");
        String approvalComment = queryMap.get("approvalComment");


        //认领组任务
        taskService.claim(taskId,username);

        //获取节点任务
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        //获取流程定义模型
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());

        //获取当前节点的定义模型
        FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());

        //转换为用户任务
        UserTask userTask = (UserTask)flowElement;

        //流程变量
        Map<String, Object> variables = new HashMap<>();

        ApproverInfo approverInfo = null;

        //获取该节点出口连线
        List<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
        if(StringUtils.isNotEmpty(outgoingFlows)){
            for(SequenceFlow sequenceFlow : outgoingFlows){
                //如果该连线名称与审批类型一致，说明该连线为将要执行的连线
                if(approval.equals(sequenceFlow.getName())){
                    //获取出线连接的目标节点
                    FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
                    if(targetFlowElement instanceof UserTask){
                        UserTask targetUserTask = (UserTask)targetFlowElement;
                        //获取该节点的审批类型
                        ApproverInfoExample approverInfoExample = new ApproverInfoExample();
                        approverInfoExample.createCriteria().andProcessDefinitionIdEqualTo(task.getProcessDefinitionId())
                                .andTaskIdEqualTo(targetUserTask.getId());
                        List<ApproverInfo> approverInfoList = approverInfoMapper.selectByExample(approverInfoExample);
                        if(StringUtils.isNotEmpty(approverInfoList) && approverInfoList.size()==1){
                            approverInfo = approverInfoList.get(0);
                            //判断审批方式，并设置审批人流程变量
                            if(approverInfo.getApprovalType().equals(ProcessContants.APPROVAL_TYPE_APPLYUSER)){
                                //如果是申请人处理，则直接设置申请人即可
                                variables.put("assigneeApply", applyUser);
                            }
                            if(approverInfo.getApprovalType().equals(ProcessContants.APPROVAL_TYPE_SINGLE)){
                                //如果是单人审批
                                variables.put("assigneeSingle", approverInfo.getApprovalUser());
                            }
                            if(approverInfo.getApprovalType().equals(ProcessContants.APPROVAL_TYPE_MANGPEOPLE)){
                                //如果是组内单人审批
                                String approvalUser = approverInfo.getApprovalUser();
                                List<String> assigneeList = Arrays.asList(approvalUser.split(";"));
                                String assignee = "";
                                for(String item : assigneeList){
                                    assignee = assignee + item + ",";
                                }
                                assignee = assignee.substring(0,assignee.length()-1);
                                variables.put("assigneeMany",assignee);
                            }
                            if(approverInfo.getApprovalType().equals(ProcessContants.APPROVAL_TYPE_COUNTERSIGN)){
                                //如果是会签
                                String approvalUser = approverInfo.getApprovalUser();
                                List<String> assigneeList = Arrays.asList(approvalUser.split(";"));
                                variables.put("assigneeList",assigneeList);
                            }
                        }
                    }
                }

            }
        }


        //处理该环节的审批
        variables.put("approval", approval);
        //添加批注，taskId,processInstance,message
        taskService.addComment(taskId, processInstanceId, approval+":"+approvalComment);
        taskService.complete(taskId, variables);


        String approvalStatus = null;
        //判断该审批流程是否结束
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        //流程是否结束标识
        boolean endFlag = true;
        if (processInstance == null) {
            //流程结束状态处理
            if("终止".equals(approval)){
                approvalStatus = "已终止";
            }
            if("同意".equals(approval)){
                approvalStatus = "审批通过";
            }
            endFlag = true;
        }else{
            //流程未结束状态处理
            if("同意".equals(approval)){
                approvalStatus = "审批中";
            }
            if("驳回".equals(approval)){
                approvalStatus = "已驳回";
            }
            if("重新申请".equals(approval)){
                approvalStatus = "审批中";
            }
            endFlag = false;
        }

        outMap.put("approvalStatus",approvalStatus);
        if(approverInfo != null){
            if(approverInfo.getApprovalType().equals(ProcessContants.APPROVAL_TYPE_APPLYUSER)){
                outMap.put("approvalUser",(String) variables.get("assigneeApply"));
            }else{
                outMap.put("approvalUser",approverInfo.getApprovalUser());
            }
            outMap.put("taskName",approverInfo.getTaskName());
        }else{
            outMap.put("approvalUser","");
            outMap.put("taskName","");
        }

        //如果流程未结束且当前处理任务为会签，则不需要更新当前环节审批人信息
        if(userTask.getId().contains("countersign")&&!endFlag){
            outMap.put("updateFlag","false");
        }else{
            //需要更新
            outMap.put("updateFlag","true");
        }

        return outMap;
    }

    /**
     * 启动审批流程，通用组件
     * @param queryMap
     * @return
     */
    @Override
    public Map<String,String> doStartProcess(Map<String,String> queryMap){
        Map<String,String> outMap = new HashMap<>(3);
        String processDefinitionKey = queryMap.get("processDefinitionKey");
        String businessId = queryMap.get("businessId");
        String applyUser = queryMap.get("applyUser");

        //以流程定义key启动流程实例，并设置流程变量，把请假单号作为businessKey传入
        //获取节点审批配置信息
        ApproverInfoExample approverInfoExample = new ApproverInfoExample();
        approverInfoExample.createCriteria()
                .andProcessDefinitionKeyEqualTo(processDefinitionKey);
        approverInfoExample.setOrderByClause(" approver_id asc");
        List<ApproverInfo> approverInfoList = approverInfoMapper.selectByExample(approverInfoExample);
        ApproverInfo approverInfo = null;
        if(StringUtils.isNotEmpty(approverInfoList)){
            approverInfo = approverInfoList.get(0);
        }

        //判断审批方式，并设置审批人流程变量
        Map<String, Object> variables = new HashMap<>();
        if(approverInfo.getApprovalType().equals(ProcessContants.APPROVAL_TYPE_APPLYUSER)){
            //如果是申请人处理，则直接设置申请人即可
            variables.put("assigneeApply", applyUser);
        }
        if(approverInfo.getApprovalType().equals(ProcessContants.APPROVAL_TYPE_SINGLE)){
            //如果是单人审批
            variables.put("assigneeSingle", approverInfo.getApprovalUser());
        }
        if(approverInfo.getApprovalType().equals(ProcessContants.APPROVAL_TYPE_MANGPEOPLE)){
            //如果是组内单人审批
            String approvalUser = approverInfo.getApprovalUser();
            List<String> assigneeList = Arrays.asList(approvalUser.split(";"));
            String assignee = "";
            for(String item : assigneeList){
                assignee = assignee + item + ",";
            }
            assignee = assignee.substring(0,assignee.length()-1);
            variables.put("assigneeMany",assignee);
        }
        if(approverInfo.getApprovalType().equals(ProcessContants.APPROVAL_TYPE_COUNTERSIGN)){
            //如果是会签
            String approvalUser = approverInfo.getApprovalUser();
            List<String> assigneeList = Arrays.asList(approvalUser.split(";"));
            variables.put("assigneeList",assigneeList);
        }

        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessId,variables);
        String processInstanceId = processInstance.getProcessInstanceId();

        outMap.put("processInstanceId",processInstanceId);
        if(approverInfo != null){
            if(approverInfo.getApprovalType().equals(ProcessContants.APPROVAL_TYPE_APPLYUSER)){
                outMap.put("approvalUser",(String) variables.get("assigneeApply"));
            }else{
                outMap.put("approvalUser",approverInfo.getApprovalUser());
            }
            outMap.put("taskName",approverInfo.getTaskName());
        }else{
            outMap.put("approvalUser","");
            outMap.put("taskName","");
        }

        return outMap;
    }
}
